﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Gezel.Model;
using Weazel.Gezel.Model.Errors;

#endregion

namespace Weazel.Gezel.Parser
{
  public static class ParseHardwired
  {
    public static readonly Set<Token> First = new Set<Token>(Token.Hardwired);

    public static void Parse(Set<Token> follow, Tokenizer t, Model.Model parent)
    {      
      Set<Token> current = new Set<Token>(
        // Token.Hardwired,
        Token.Identifier,
        Token.LeftParenthesis,
        Token.RightParenthesis,
        Token.LeftBrace,
        Token.RightBrace
      );

      current = current.Union(ParseHardwiredDefinition.First);

			Position startPosition = t.CurrentPosition;

      t.Accept(Token.Hardwired, follow.Union(current));

      string name = t.CurrentToken == Token.Identifier ? t.CurrentString : null;

      Controller controller = new Controller(parent, name, startPosition, null);
      controller.Type = Controller.ControllerType.Hardwired;

      // token identifier not removed here
      t.Accept(Token.Identifier, follow.Union(current));

      current.Remove(Token.LeftParenthesis);
      t.Accept(Token.LeftParenthesis, follow.Union(current));

      controller.DatapathRef = t.CurrentToken == Token.Identifier ? t.CurrentString : null;

      current.Remove(Token.Identifier);
      t.Accept(Token.Identifier, follow.Union(current));

      current.Remove(Token.RightParenthesis);
      t.Accept(Token.RightParenthesis, follow.Union(current));

      current.Remove(Token.LeftBrace);
      t.Accept(Token.LeftBrace, follow.Union(current));

      current.Remove(ParseHardwiredDefinition.First);
      ParseHardwiredDefinition.Parse(follow.Union(current), t, controller);

			controller.EndPosition = t.CurrentEndPosition;

      current.Remove(Token.RightBrace);
      t.Accept(Token.RightBrace, follow.Union(current));

      if (name != null && controller.DatapathRef != null)
      {
        if (parent.Controllers.ContainsKey(name))
        {
          t.Errors.Add(
            new DuplicateControllerNameParseError(
              controller,
              parent.Controllers[name]
            )
          );
        }
        else
        {
          parent.Controllers.Add(name, controller);
        }
      }
    }
  }

  public static class ParseHardwiredDefinition
  {
    public static readonly Set<Token> First = new Set<Token>(Token.Identifier);

    public static void Parse(Set<Token> follow, Tokenizer t, Controller controller)
    {      
      Set<Token> current = new Set<Token>(
        Token.Identifier,
        Token.TraceDirective,
        Token.Semicolon
      );

      bool done = false;

      do
      {
        t.Check(follow.Union(current));

        if (t.CurrentToken == Token.Identifier)
        {
          controller.SignalFlowGraphRefs.Add(t.CurrentString);
          t.Accept(Token.Identifier, follow.Union(current));
          t.Accept(Token.Semicolon, follow.Union(current));
        }
      
        //    TODO: hvad med tracing her ?

        else if (t.CurrentToken == Token.TraceDirective)
        {
          /*
          controller.tr
          t.Accept(Token.TraceDirective, follow.Union(current));
          t.Accept(Token.Semicolon, follow.Union(current));
          */
          throw new NotImplementedException("Trace in hardwired sfg list not implemented");
        }
        
        else
        {
          done = true;
        }
      } while (!done);
    }
  }
}
